package br.com.srv.componentes.relatorio.pontoparada.service;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import br.com.srv.componentes.jdbcdao.DadosLidoJdbcDAO;
import br.com.srv.model.PeriodoTO;
import br.com.srv.util.DateHelper;

public class PontoParadaServiceImpl implements PontoParadaService {
	
	DadosLidoJdbcDAO dadosLidoJdbcDAO;
	
	public List<Map<String, String>> consultaPontosParadaByVeiculo(
			String veiculoId, Long velMinima, Long tempoParada,
			PeriodoTO periodoTO) throws Exception {
		
		//pega os dias do intervalo
		List<String> listaDias = DateHelper.getListOfDays(
				periodoTO.getDataInicial(), periodoTO.getDataFinal());
		
		ArrayList pontosParadas = new ArrayList();
		
		for (String dia : listaDias) {
			
			HashMap diaMap = new HashMap(2);
			diaMap.put("dia", dia);
			
			List<Map<String, String>> pontos =
				getDadosLidoJdbcDAO().consultaPontosByVeiculo(veiculoId, dia, periodoTO.getHoraInicial(), periodoTO.getHoraFinal());
			
			float distancia = 0; //distancia entre paradas
			float kmHora = 0; //
			float medicoes = 0;
			Map lastPonto = null;
			Map lastPontoParada = null;
			
			Map iniPonto = null;
			Map fimPonto = null;
			ArrayList paradas = new ArrayList(); // Lista de paradas por dia
			
			for (Iterator iterator = pontos.iterator(); iterator.hasNext();) {
				
				Map ponto = (Map) iterator.next();
				
				if (lastPonto == null) {
					lastPonto = ponto;
				}
				/*
				 * Se velocidade <= a velocidade m�nima, ent�o velocidade = 0 (parado)
				 */
				Float velocidade = new Float(ponto.get("VEL").toString());
				velocidade = (velocidade <= velMinima) ? 0.0F : velocidade; 

				/*
				 * Verifica velocidade 
				 */
				if (velocidade == 0 && lastPonto.get("NEAR_ID").equals(ponto.get("NEAR_ID"))) {
					if (iniPonto == null) {
						iniPonto = lastPonto;
					}
					fimPonto = (iniPonto != null && !iterator.hasNext()) ? ponto : null;
				} else {
					fimPonto = (iniPonto != null) ? lastPonto : null;
					distancia += Float.parseFloat(ponto.get("NEAR_DIST").toString());
					if (velocidade > 0) {
						kmHora += Float.parseFloat(ponto.get("VEL").toString());
						medicoes++;
					}
				}
				if (fimPonto == null && !iterator.hasNext()) {
					fimPonto = ponto;
				}
				/*
				 * Se uma parada for identificada
				 */
				if (iniPonto != null && fimPonto != null) {
					Long duracao = extractTimeMillis(iniPonto, fimPonto);
					
					/*
					 * Se for uma parada dentro do tempo m�nimo
					 */
					if ((duracao/60000) >= tempoParada) {
						Date data1 = DateHelper.parseDate(DateHelper.REPORT_DATE_DEFAULT, iniPonto.get("DATE_TIME").toString());
						Date data2 = DateHelper.parseDate(DateHelper.REPORT_DATE_DEFAULT, fimPonto.get("DATE_TIME").toString());
						
						HashMap parada = new HashMap(12);
						parada.put("NEAR_ID", fimPonto.get("NEAR_ID"));
						parada.put("DESC", fimPonto.get("NEAR_DESC"));
						parada.put("NEAR_DIST", fimPonto.get("NEAR_DIST"));
						parada.put("DISTANCIA", Float.valueOf(distancia/1000));
						parada.put("TEMPO", (lastPontoParada == null) ? Long.valueOf(0) : extractTimeMillis(lastPontoParada, iniPonto));
						parada.put("VEL_MEDIA", (medicoes > 1) ? Float.valueOf(kmHora / medicoes) : 0.0 );
						parada.put("HORA_INICIAL", DateHelper.parseString("HH:mm:ss", data1));
						parada.put("HORA_FINAL", DateHelper.parseString("HH:mm:ss", data2));
						parada.put("X", fimPonto.get("X"));
						parada.put("Y", fimPonto.get("Y"));
						parada.put("IGNITION", (fimPonto.get("IGNITION").equals("1")) ? "Sim" : "N�o" );
						parada.put("DURACAO", duracao);							
						paradas.add(parada);
						
						lastPontoParada = fimPonto;
						if (medicoes > 1) {
							distancia = 0;
							kmHora = 0;
							medicoes = 0;
						}
					}
					
					iniPonto = null;
					fimPonto = null;
				}
				lastPonto = ponto;								
			}
			
			paradas.trimToSize();
			diaMap.put("paradas", paradas);
			pontosParadas.add(diaMap);
			
		}
		
		return pontosParadas;
	}
	
	private Long extractTimeMillis(Map ponto1, Map ponto2) throws ParseException {
		long data1 = DateHelper.parseDate(DateHelper.REPORT_DATE_DEFAULT, ponto1.get("DATE_TIME").toString()).getTime();
		long data2 = DateHelper.parseDate(DateHelper.REPORT_DATE_DEFAULT, ponto2.get("DATE_TIME").toString()).getTime();
		return Long.valueOf(data2 - data1);
	}	

	public DadosLidoJdbcDAO getDadosLidoJdbcDAO() {
		return dadosLidoJdbcDAO;
	}

	public void setDadosLidoJdbcDAO(DadosLidoJdbcDAO dadosLidoJdbcDAO) {
		this.dadosLidoJdbcDAO = dadosLidoJdbcDAO;
	}

}
